package ru.bragnikita.utils.swing.widget.mult;

import org.apache.commons.lang3.ObjectUtils;
import ru.bragnikita.utils.swing.widget.WtAbstractTextWidget;
import ru.bragnikita.utils.swing.widget.WtListWidget;
import ru.bragnikita.utils.swing.widget.common.EventSupport;
import ru.bragnikita.utils.swing.widget.field.Field;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.List;

/**
 * @author Nikita.Brazhnikov
 */
public class WtTextComboBox<V> extends WtAbstractTextWidget<JComboBox<V>> implements WtListWidget<JComboBox<V>, V> {

    private Field field;
    private EventSupport<ItemsListener<V>, ru.bragnikita.utils.swing.widget.mult.ItemEvent<V>> eventSupport;
    private List<V> model;

    public WtTextComboBox(String id) {
        super(id);
        eventSupport = new EventSupport<ItemsListener<V>, ru.bragnikita.utils.swing.widget.mult.ItemEvent<V>>() {
            @Override
            protected void listenerCall(ItemsListener<V> listener, ru.bragnikita.utils.swing.widget.mult.ItemEvent<V> event) {
                switch (event.getType()) {
                    case "select":
                        listener.onSelect(event);
                        break;
                    case "unselect":
                        listener.onDeselect(event);
                        break;
                    default:
                }
                listener.onEvent(event);
            }
        };
        setComponent(new JComboBox<V>());
        getComponent().addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    final V modelItem = (V) e.getItem();
                    fireSelectionChanged(null, modelItem);
                }
            }
        });
        getComponent().setRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                JLabel label = (JLabel) super
                     .getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                label.setText(field.getAsString(value));
                return label;
            }
        });

    }

    public WtTextComboBox(Field field) {
        this(field.getId());
        this.field = field;
    }

    @Override
    public V getSelectedValue() {
        return (V) getComponent().getModel().getSelectedItem();
    }

    public V getValue(int index) {
        int size = getComponent().getModel().getSize();
        if (index > size - 1)
            return null;
        return getComponent().getModel().getElementAt(index);
    }

    public V getFirst() {
        return getValue(0);
    }

    public V getLast() {
        return getValue(getComponent().getModel().getSize() - 1);
    }

    @Override
    public String getAsString() {
        return ObjectUtils.toString(getSelectedValue(), null);
    }

    @Override
    public V getValue() {
        return getSelectedValue();
    }

    @Override
    public void setValue(Object value) {
        //TODO allow to add lists and single values
        throw new UnsupportedOperationException("Not supported");
    }

    public void repaint() {
        final DefaultComboBoxModel<V> defaultComboBoxModel = new DefaultComboBoxModel<>();
        for (V v : model) {
            defaultComboBoxModel.addElement(v);
        }
        getComponent().setModel(defaultComboBoxModel);
        getComponent().repaint();
    }

    public void fireSelectionChanged(V from, V to) {
        ru.bragnikita.utils.swing.widget.mult.ItemEvent<V> event;
        if (from != null) {
            event = new ru.bragnikita.utils.swing.widget.mult.ItemEvent<V>(to, "unselect");
            eventSupport.fireEvent(event);
        }
        if (to != null) {
            event = new ru.bragnikita.utils.swing.widget.mult.ItemEvent<V>(to, "select");
            eventSupport.fireEvent(event);
        }
    }

    public void setModel(List<V> model) {
        this.model = model;
        repaint();
    }

    public void setSelected(final V value) {
        repaint();
        getComponent().setSelectedItem(value);
    }

    public EventSupport<ItemsListener<V>, ru.bragnikita.utils.swing.widget.mult.ItemEvent<V>> getEventSupport() {
        return eventSupport;
    }


}
